//
//  ZYMachExceptionHandler.m
//  ZYWebImage
//
//  Created by wangzhipan on 2025/5/3.
//

#import "ZYMachExceptionHandler.h"
#import <mach/mach.h>
#import <pthread.h>
#import <mach/mach_error.h>
#import <mach/exc.h>
#import "ZYCrashReportGenerator.h"

static const char *machExceptionName(exception_type_t exceptionType)
{
    switch (exceptionType) {
        case EXC_BAD_ACCESS:        return "EXC_BAD_ACCESS";       //内存访问错误，如访问已释放的内存、空指针或非法地址
        case EXC_BAD_INSTRUCTION:   return "EXC_BAD_INSTRUCTION";  //非法指令，如执行了无效的CPU指令，通常由代码损坏或编译器错误导致
        case EXC_ARITHMETIC:        return "EXC_ARITHMETIC";       //算术错误，如除零、浮点溢出等数学运算错误
        case EXC_EMULATION:         return "EXC_EMULATION";        //指令模拟错误，通常在模拟不支持的硬件指令时发生
        case EXC_SOFTWARE:          return "EXC_SOFTWARE";         //软件触发的异常，如abort()函数调用
        case EXC_BREAKPOINT:        return "EXC_BREAKPOINT";       //断点异常，由调试器设置的断点或异常断点触发
        case EXC_SYSCALL:           return "EXC_SYSCALL";          //系统调用异常，系统调用参数错误
        case EXC_MACH_SYSCALL:      return "EXC_MACH_SYSCALL";     //Mach系统调用异常，Mach系统调用参数错误
        case EXC_RPC_ALERT:         return "EXC_RPC_ALERT";        //RPC警告，远程过程调用异常
        case EXC_CRASH:             return "EXC_CRASH";            //系统强制终止应用，通常由watchdog触发或系统内存压力导致
        case EXC_RESOURCE:          return "EXC_RESOURCE";         //资源限制异常，如CPU使用过高、内存使用超限等
        case EXC_GUARD:             return "EXC_GUARD";            //内核保护异常，违反了系统保护机制，如文件描述符保护
        default:                    return "UNKNOWN";             // 未知异常类型
    }
}

static const char *machCodeName(exception_type_t exceptionType, mach_exception_code_t code)
{
    switch (exceptionType) {
        case EXC_BAD_ACCESS: {
            switch (code) {
                case KERN_INVALID_ADDRESS:    return "KERN_INVALID_ADDRESS";    // 无效地址访问，如空指针或已释放内存
                case KERN_PROTECTION_FAILURE: return "KERN_PROTECTION_FAILURE"; // 内存保护错误，如写入只读内存
                default:                      return "UNKNOWN";                 // 其他内存访问错误
            }
        }
        default:        return "UNKNOWN"; // 其他异常类型的代码
    }
}

// Mach异常处理线程相关变量
static mach_port_t exceptionPort = MACH_PORT_NULL;  //Mach异常端口，用于接收异常消息
static pthread_t machExceptionThread;               //异常处理线程
static bool isThreadRunning = false;                //线程运行状态标志
static bool isHandlerInstalled = false;              //处理器安装状态标志


// 添加自定义异常消息结构定义
typedef struct {
    mach_msg_header_t           header;
    mach_msg_body_t             body;
    mach_msg_port_descriptor_t  thread;
    mach_msg_port_descriptor_t  task;
    NDR_record_t                ndr;
    exception_type_t            exception;
    mach_msg_type_number_t      codeCnt;
    int64_t                     code[2];
} zy_exception_message_t;

#define MAX_EXCEPTION_MESSAGE_SIZE 1024

/**
 * Mach异常处理线程函数
 * 该线程专门用于接收和处理Mach异常消息
 * @param unused 未使用的参数
 * @return 线程返回值（未使用）
 */

static void *machExceptionHandlerThread(void *unused)
{
    @autoreleasepool {
        //设置线程名称，便于调试
        pthread_setname_np("ZYMachExceptionHandler");

                
        // 定义消息缓冲区
        char messageBuffer[MAX_EXCEPTION_MESSAGE_SIZE];
        char replyBuffer[MAX_EXCEPTION_MESSAGE_SIZE];
        
        while (isThreadRunning) {
            // 清空消息缓冲区
            memset(messageBuffer, 0, MAX_EXCEPTION_MESSAGE_SIZE);
            memset(replyBuffer, 0, MAX_EXCEPTION_MESSAGE_SIZE);
            
            
            // 设置消息头指针，用于mach_msg函数
            mach_msg_header_t* receiveMessage = (mach_msg_header_t*)messageBuffer;
            mach_msg_header_t* sendMessage = (mach_msg_header_t*)replyBuffer;
            
            // 接收异常消息
            // MACH_RCV_MSG: 接收消息模式
            // MACH_RCV_LARGE: 如果消息太大，允许重新分配缓冲区
            // 接收异常消息
            kern_return_t kr = mach_msg(
                receiveMessage,                // 接收消息的缓冲区
                MACH_RCV_MSG | MACH_RCV_LARGE, // 接收选项
                0,                             // 发送大小（不发送，所以为0）
                MAX_EXCEPTION_MESSAGE_SIZE,    // 接收缓冲区大小
                exceptionPort,                 // 接收端口
                MACH_MSG_TIMEOUT_NONE,         // 无超时
                MACH_PORT_NULL                 // 超时端口（不使用）
            );
            
            if (kr != KERN_SUCCESS) {
                continue;  // 接收消息失败，继续等待下一个消息
            }
            
            // 将消息转换为我们的自定义结构
            zy_exception_message_t* excMsg = (zy_exception_message_t*)receiveMessage;
            
            // 直接从消息结构中获取异常类型和代码
            exception_type_t exceptionType = excMsg->exception;
            mach_exception_data_type_t codeCount = excMsg->codeCnt;
            int64_t* codes = excMsg->code;
            
            // 构建异常信息，用于生成崩溃报告
            NSString *exceptionName = [NSString stringWithFormat:@"Mach Exception: %s", machExceptionName(exceptionType)];
            NSString *codeName = (codeCount > 0) ? [NSString stringWithFormat:@"%s", machCodeName(exceptionType, codes[0])] : @"Unknown";
            NSString *reason = [NSString stringWithFormat:@"Mach异常: %@ (代码: %@)", exceptionName, codeName];
            
            // 构建用户信息字典，包含异常详情
            NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
            userInfo[@"exceptionType"] = @(exceptionType);
            
            if (codeCount > 0) {
                userInfo[@"code"] = @(codes[0]);  // 异常代码
                
                // 对于内存访问错误，记录错误地址
                // codes[0]通常是错误类型，codes[1]通常是错误地址
                if (exceptionType == EXC_BAD_ACCESS && codeCount > 1) {
                    userInfo[@"address"] = @(codes[1]);  // 错误内存地址
                }
            }
            
            // 生成崩溃报告
            [[ZYCrashReportGenerator sharedInstance] generateReportWithType:ZYCrashTypeMach
                                                                       name:exceptionName
                                                                     reason:reason
                                                                   userInfo:userInfo];
                        
            // 回复异常消息，告知系统我们已处理异常
            // 注意：在实际应用中，可能需要将异常转发给系统默认处理器
            kr = mach_msg(
                sendMessage,              // 发送消息的缓冲区
                MACH_SEND_MSG,            // 发送选项
                MAX_EXCEPTION_MESSAGE_SIZE,     // 发送消息大小，使用缓冲区大小
                0,                        // 接收大小（不接收，所以为0）
                MACH_PORT_NULL,           // 接收端口（不接收，所以为NULL）
                MACH_MSG_TIMEOUT_NONE,    // 无超时
                MACH_PORT_NULL            // 超时端口（不使用）
            );
            
            // 处理完异常后终止应用
            // 使用SIGKILL确保应用终止，避免在不稳定状态下继续运行
            // SIGKILL信号不能被捕获或忽略，确保进程终止
            kill(getpid(), SIGKILL);
        }
    }
    return NULL;
}

@implementation ZYMachExceptionHandler
- (BOOL)install
{
    if (isHandlerInstalled) {
        return YES;
    }
    
    @synchronized (self) {
        if (isHandlerInstalled) {
            return YES;
        }
        //创建Mach异常端口，用于接收异常消息
        kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exceptionPort);
        if (kr != KERN_SUCCESS) {
            NSLog(@"Failed to allocate mach port: %s", mach_error_string(kr));
            return NO;
        }
        
        // 插入发送权限，允许向该端口发送消息
        kr = mach_port_insert_right(mach_task_self(), exceptionPort, exceptionPort, MACH_MSG_TYPE_MAKE_SEND);
        
        if (kr != KERN_SUCCESS) {
            NSLog(@"Failed to insert right: %s", mach_error_string(kr));
            mach_port_deallocate(mach_task_self(), exceptionPort);
            return NO;
        }
        
        // 设置异常端口，指定我们关心的异常类型
        // 这些异常类型覆盖了大多数常见的崩溃情况
        exception_mask_t exceptionMask = EXC_MASK_BAD_ACCESS |      // 内存访问错误
                                         EXC_MASK_BAD_INSTRUCTION |  // 非法指令
                                         EXC_MASK_ARITHMETIC |       // 算术错误
                                         EXC_MASK_SOFTWARE |         // 软件触发的异常
                                         EXC_MASK_BREAKPOINT;        // 断点异常
        // 将我们的端口注册为任务的异常端口
        // EXCEPTION_DEFAULT: 默认异常行为
        // MACH_EXCEPTION_CODES: 使用Mach异常代码
        // THREAD_STATE_NONE: 不需要线程状态
        kr = task_set_exception_ports(mach_task_self(),
                                      exceptionMask,
                                      exceptionPort,
                                      EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
                                      THREAD_STATE_NONE);
        if (kr != KERN_SUCCESS) {
            NSLog(@"Failed to set exception ports: %s", mach_error_string(kr));
            mach_port_deallocate(mach_task_self(), exceptionPort);
            return NO;
        }
        
        // 启动异常处理线程，专门用于接收和处理异常消息
        isThreadRunning = YES;
        int result = pthread_create(&machExceptionThread, NULL, machExceptionHandlerThread, NULL);
        if (result != 0) {
            NSLog(@"Failed to create mach exception thread: %d", result);
            mach_port_deallocate(mach_task_self(), exceptionPort);
            isThreadRunning = false;
            return NO;
        }
        isHandlerInstalled = YES;
        return YES;
    }
}

- (void)uninstall
{
    @synchronized (self) {
        if (!isHandlerInstalled) {
            return;
        }
        
        // 停止异常处理线程
        isThreadRunning = NO;
        // 向异常端口发送消息，唤醒线程
        // 因为线程可能在mach_msg中阻塞，需要中断它
        mach_port_t thread_port = pthread_mach_thread_np(machExceptionThread);
        thread_abort(thread_port);
        
        //等待线程结束，确保资源正确释放
        pthread_join(machExceptionThread, NULL);
        
        //释放异常端口，清理资源
        mach_port_deallocate(mach_task_self(), exceptionPort);
        exceptionPort = MACH_PORT_NULL;
        
        isHandlerInstalled = NO;
    }
}
@end
